﻿using Se.Common;
using Se.Log;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Se.Data
{
    public abstract class DBProviderBase
    {
        public DBProviderBase(string connectionString)
        {
            this.ConnectionString = connectionString;
        }

        #region Members

        /// <summary>
        /// 连接字符串
        /// </summary>
        public string ConnectionString { get; private set; }


        #endregion


        #region abstract Methods

        /// <summary>
        /// 检查是否连接
        /// </summary>
        /// <returns></returns>
        public abstract void CheckConnect();

        /// <summary>
        /// 执行Sql（返回查询reader）
        /// </summary>
        /// <param name="cmdType"></param>
        /// <param name="cmdText"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public abstract IDataReader ExecuteReader(CommandType cmdType, string cmdText, params IDataParameter[] parameters);
        /// <summary>
        /// 执行sql(返回DataSet)
        /// </summary>
        /// <param name="cmdType"></param>
        /// <param name="cmdText"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public abstract DataSet ExecuteDataSet(CommandType cmdType, string cmdText, params IDataParameter[] parameters);
        /// <summary>
        /// 执行Sql，返回第一行第一列的结果
        /// </summary>
        /// <param name="cmdType"></param>
        /// <param name="cmdText"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public abstract object ExecuteScalar(CommandType cmdType, string cmdText, params IDataParameter[] parameters);
        /// <summary>
        /// 执行Sql，返回行数
        /// </summary>
        /// <param name="cmdType"></param>
        /// <param name="cmdText"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public abstract int ExecuteQuery(CommandType cmdType, string cmdText, params IDataParameter[] parameters);
        /// <summary>
        /// 执行Sql，返回行数
        /// </summary>
        /// <param name="transactionName"></param>
        /// <param name="cmdType"></param>
        /// <param name="cmdText"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public abstract ResultInfo ExecuteTransactionQuery(string transactionName, CommandType cmdType, string cmdText, params IDataParameter[] parameters);
        /// <summary>
        /// 写入消息队列(不用)
        /// </summary>
        /// <param name="identityId"></param>
        /// <param name="commandType"></param>
        /// <param name="commandText"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public abstract int ExecuteNonQuery(int identityId, CommandType commandType, string commandText, params IDataParameter[] parameters);
        /// <summary>
        /// 检查表是否存在，并返回行
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public abstract bool CheckTable(string tableName, out DBColumn[] columns);
        /// <summary>
        /// 创建表
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="columns"></param>
        public abstract void CreateTable(string tableName, DBColumn[] columns);
        /// <summary>
        /// 创建列
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="columns"></param>
        public abstract void CreateColumn(string tableName, DBColumn[] columns);

        /// <summary>
        /// 创建参数
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public abstract IDataParameter CreateParameter(string paramName, object value);

        /// <summary>
        /// 创建参数
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="dbType"></param>
        /// <param name="size"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public abstract IDataParameter CreateParameter(string paramName, int dbType, int size, object value);
        /// <summary>
        /// 格式化名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public abstract string FormatName(string name);
        /// <summary>
        /// 格式化Select语句中的列名
        /// </summary>
        /// <param name="splitChar"></param>
        /// <param name="columns"></param>
        /// <returns></returns>
        public abstract string FormatQueryColumn(string splitChar, ICollection<string> columns);



        /// <summary>
        /// 转换为SqlDbType
        /// </summary>
        /// <param name="sqlDbType"></param>
        /// <returns></returns>
        public virtual SqlDbType ConvertToDbType(string sqlDbType)
        {
            SqlDbType dbType = SqlDbType.Variant;//默认为Object

            switch (sqlDbType)
            {
                case "int":
                    dbType = SqlDbType.Int;
                    break;
                case "varchar":
                    dbType = SqlDbType.VarChar;
                    break;
                case "bit":
                    dbType = SqlDbType.Bit;
                    break;
                case "datetime":
                    dbType = SqlDbType.DateTime;
                    break;
                case "decimal":
                    dbType = SqlDbType.Decimal;
                    break;
                case "float":
                    dbType = SqlDbType.Float;
                    break;
                case "image":
                    dbType = SqlDbType.Image;
                    break;
                case "money":
                    dbType = SqlDbType.Money;
                    break;
                case "ntext":
                    dbType = SqlDbType.NText;
                    break;
                case "nvarchar":
                    dbType = SqlDbType.NVarChar;
                    break;
                case "smalldatetime":
                    dbType = SqlDbType.SmallDateTime;
                    break;
                case "smallint":
                    dbType = SqlDbType.SmallInt;
                    break;
                case "text":
                    dbType = SqlDbType.Text;
                    break;
                case "bigint":
                    dbType = SqlDbType.BigInt;
                    break;
                case "binary":
                    dbType = SqlDbType.Binary;
                    break;
                case "char":
                    dbType = SqlDbType.Char;
                    break;
                case "nchar":
                    dbType = SqlDbType.NChar;
                    break;
                case "numeric":
                    dbType = SqlDbType.Decimal;
                    break;
                case "real":
                    dbType = SqlDbType.Real;
                    break;
                case "smallmoney":
                    dbType = SqlDbType.SmallMoney;
                    break;
                case "sql_variant":
                    dbType = SqlDbType.Variant;
                    break;
                case "timestamp":
                    dbType = SqlDbType.Timestamp;
                    break;
                case "tinyint":
                    dbType = SqlDbType.TinyInt;
                    break;
                case "uniqueidentifier":
                    dbType = SqlDbType.UniqueIdentifier;
                    break;
                case "varbinary":
                    dbType = SqlDbType.VarBinary;
                    break;
                case "xml":
                    dbType = SqlDbType.Xml;
                    break;
            }
            return dbType;
        }

        #endregion

        /// <summary>
        /// 执行Sql，返回第一行
        /// </summary>
        /// <param name="cmdType"></param>
        /// <param name="cmdText"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public DataRow ExecuteDataRow(CommandType cmdType, string cmdText, params IDataParameter[] parameters)
        {
            var dataSet = this.ExecuteDataSet(cmdType, cmdText, parameters);
            if (dataSet.Tables.Count > 0 && dataSet.Tables[0].Rows.Count > 0)
            {
                return dataSet.Tables[0].Rows[0];
            }
            return null;
        }


        #region Methods
        /// <summary>
        /// 转换Data参数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="parameters"></param>
        /// <returns></returns>
        protected T[] ConvertParams<T>(IDataParameter[] parameters)
        {
            if (parameters == null)
            {
                return null;
            }

            List<T> list = new List<T>();
            foreach (var parameter in parameters)
            {
                if (parameter != null)
                    list.Add((T)parameter);
            }

            return list.ToArray();
        }

        #endregion
    }
}
